Published on

폼 레이아웃을 도와주는 다른 방법들

Authors
  • avatar
    Name
    Hyo814
    Twitter

폼 레이아웃을 도와주는 다른 방법들(Form.py)

공식 문서 :

https://docs.djangoproject.com/en/5.2/topics/forms/modelforms/

https://django-crispy-forms.readthedocs.io/en/latest/

https://django-tailwind.readthedocs.io/en/latest/

https://forum.djangoproject.com/t/django-formify-a-django-form-rendering-package-for-tailwind-css-enthusiasts/34904

https://django-formify.readthedocs.io/en/latest/

기타사항.

https://github.com/elo80ka/django-dynamic-formset

https://github.com/jazzband/django-widget-tweaks

https://github.com/elo80ka/django-dynamic-formset

https://django-bootstrap5.readthedocs.io/en/latest/

라이브러리구조 제어스타일 프레임워크 연동주요 특징
django-crispy-formsBootstrap / TailwindPython 코드로 레이아웃 제어
django-formifyTailwind 전용컴포넌트 기반 구조 설계
django-widget-tweaks자유 (템플릿에서 조작)템플릿에서 필드 속성 조작
django-bootstrap5Bootstrap 전용자동 렌더링, 커스터마이징은 제한
django-dynamic-formset자유 (JS 조작 중심)클라이언트에서 Form 행 추가/삭제

1. 위젯(widget) 커스터마이징

forms.CharField(
    widget=forms.TextInput(attrs={
        "class": "input input-bordered",
        "placeholder": "이름을 입력하세요",
        "autocomplete": "off",
        "maxlength": "30",
        "required": "required"
    })
)

자주 사용하는 HTML 속성 (Tailwind 포함)

  • class, placeholder, type, autocomplete, maxlength, required, readonly, disabled, id, data-*
  • <textarea> 전용: rows, cols
  • 입력 제한: min, max, minlength, pattern, step

2. forms.Field 공통 속성 확장

속성설명
label레이블 텍스트
help_text입력 안내 문구
error_messages유효성 검사 실패 시 메시지
initial기본값
required필수 여부 (기본값: True)
disabled비활성화 설정
widget위젯 지정
validators커스텀 유효성 검사 함수 리스트
localize로컬라이징 포맷 사용 여부
input_formats날짜/시간 허용 포맷 리스트

3. ModelForm.Meta 속성 정리

속성설명
model연결할 모델 클래스
fields포함할 필드 목록
exclude제외할 필드 목록
widgets필드별 위젯 커스터마이징
labels필드 레이블 지정
help_texts필드별 안내 문구
error_messages필드별 에러 메시지
localized_fields포맷 로컬라이징할 필드
field_classes필드 클래스 직접 지정

4. crispy_forms + ModelForm Layout 구성

self.helper.layout = Layout(
    Row(
        Column('username', css_class='w-full'),
        Column('email', css_class='w-full'),
    ),
    Row(
        Column('birth_date', css_class='w-full'),
        Column('phone', css_class='w-full'),
    ),
    Submit('submit', '저장하기', css_class='btn btn-primary w-full')
)

그룹화 및 커스텀 HTML 삽입 예시

self.helper.layout = Layout(
    HTML("<h3 class='text-lg font-bold mb-4'>기본 정보</h3>"),
    Row(Column('username'), Column('email')),
    HTML("<h3 class='text-lg font-bold mt-6 mb-4'>기타 정보</h3>"),
    Row(Column('birth_date'), Column('phone')),
    Submit('submit', '수정하기')
)


5. 조건부 렌더링 및 필드 처리

def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    super().__init__(*args, **kwargs)
    if not user.is_staff:
        self.fields.pop('phone')
    self.fields['email'].widget = forms.HiddenInput()
    self.fields['username'].disabled = True


6. Form vs ModelForm 비교 요약

항목forms.Formforms.ModelForm
모델 연결없음있음 (Meta.model)
필드 정의수동 정의모델 기반 자동 생성
Meta 클래스선택필수
저장 방식.cleaned_data 직접 처리.save() 자동 저장
활용 예검색, 문의, 확인 입력 등등록, 수정, 저장 필요 폼

7. 예시 코드: forms.Form

class ContactForm(forms.Form):
    name = forms.CharField(max_length=30)
    message = forms.CharField(widget=forms.Textarea)

8. 예시 코드: forms.ModelForm

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']
        widgets = {
            'content': forms.Textarea(attrs={
                "class": "w-full p-3 border rounded-md",
                "placeholder": "내용을 입력하세요"
            })
        }